package us.kg.kotoriforest.spring.tx.service.impl;

import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import us.kg.kotoriforest.spring.tx.dao.AccountDao;
import us.kg.kotoriforest.spring.tx.dao.BookDao;
import us.kg.kotoriforest.spring.tx.pojo.Book;
import us.kg.kotoriforest.spring.tx.service.AccountService;

import java.math.BigDecimal;

/**
 * @author Kotori rotroutine@163.com
 * @since 2025/1/31
 */
@Service
@AllArgsConstructor
public class AccountServiceImpl implements AccountService {
    private final BookDao bookDao;
    private final AccountDao accountDao;

    @Override
    @Transactional(rollbackFor = Exception.class)
    /*
        声明式事务@Transactional
        由事务管理器TransactionManager来管理事务 和 事务拦截器TransactionInterceptor来拦截事务
        事务管理器负责事务的提交、回滚、开启和关闭 事务拦截器负责决定何时开启事务、何时提交事务、何时回滚事务
            timeout - 事务超时时间，默认-1，单位秒 如果超过这个时间，事务自动回滚
                      此处的时间指的是从进入函数开始到最后一次数据库操作结束的时间
            readonly - 是否只读事务，默认false，如果是只读事务，那么在事务期间只能查询数据，不能修改数据
                       只读事务可以提高事务的并发处理能力 并且提高事务的执行性能
            rollbackFor - 回滚异常类型，默认空数组，如果遇到这些异常，事务回滚
                          Spring默认只对运行时异常（非受检异常）进行回滚 如果需要对检查异常进行回滚，需要在rollbackFor中指定异常类型
     */
    public boolean checkout(int accountId, int bookId, int quantity) {
        // 获取书籍信息
        Book book = bookDao.getBookById(bookId);

        // 获取账户需要扣减的金额
        BigDecimal amount = book.getPrice().multiply(BigDecimal.valueOf(quantity));

        // 扣减账户金额
        accountDao.decreaseAccountBalance(accountId, amount);

        // 扣减书籍库存
        bookDao.decreaseBookStock(bookId, quantity);

        return true;
    }
}
